
#include "CobwebBDB.h"
#include "Debug.h"

CobWebBDB:: CobWebBDB(const char *name, const char *home)
{
  m_dbHome = home;
  m_dbName = name;
}

CobWebBDB:: ~CobWebBDB()
{
	if(db != NULL)
		db->close(0);

	if(dbenv != NULL)
	{
		dbenv->close(0);
		delete dbenv;
	}
}

bool CobWebBDB :: Initialize()
{
	try {
		dbenv = new DbEnv(0);
		dbenv->set_error_stream(&cerr);
		dbenv->set_errpfx("cobweb");
		// We want to specify the shared memory buffer pool cachesize,
		// but everything else is the default.
		dbenv->set_cachesize(0, 64 * 1024, 0);
		// Databases are in a subdirectory.
		(void)dbenv->set_data_dir( m_dbHome.c_str());
		// Open the environment with full transactional support.
		// const char *home = "data";
		dbenv->open(m_dbHome.c_str(),  DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN, 0);
		db =  new Db(dbenv, 0);
		/*
		   db.set_error_stream(&cerr);
		   db.set_errpfx("test");
		   db.set_pagesize(1024);	
		   db.set_cachesize(0, 32 * 1024, 0);
		 */
		db->open(0, m_dbName.c_str(), "cobweb", DB_BTREE, DB_CREATE , 0664);
	}
	catch (DbException &dbe) {
		cerr << "cobweb: " << dbe.what() << "\n";
		return false;
	}
        return true;
}

bool CobWebBDB :: Save(char *key, uint32_t klen, char *val, uint32_t vlen )
{
	try{
		int ret;
		Dbt bkey(key, klen + 1);
		Dbt bdata(val, vlen + 1);
		ret = db->put(0, &bkey, &bdata, DB_NOOVERWRITE);
                DEBUG2("Save is : ", ret);
		return ret == 0 ? true : false;
	}catch(DbException &dbe)
	{
		cerr << "cobweb: " << dbe.what() << "\n";
		return false;
	}
}

bool CobWebBDB :: Replace(char *key, uint32_t klen, char *val, uint32_t vlen )
{
	try{
		int ret;
		Dbt bkey(key, klen + 1);
		Dbc *dbc;
		if((ret =  db->cursor(0, &dbc, 0)) != 0)
                {
                        DEBUG1("db->cursor create error!");  
			return false;
                }

		Dbt bdata(val, vlen + 1);
		Dbt bval;
		ret = dbc->get(&bkey, &bval, DB_SET);
		if(ret == 0){
			DEBUG1("YES data is had, so update!");
			dbc->put(&bkey, &bdata, DB_CURRENT);
		}
		else{
			DEBUG1("NO DATA, SO INSERT");
			this->Save(key, klen, val, vlen);
		}
		dbc->close();
		// ret = db->put(0, &bkey, &bdata, DB_NOOVERWRITE);
	}
	catch (DbException &dbe) {
		cerr << "cobweb: " << dbe.what() << "\n";
		return false;
	}
	return true;
}

bool CobWebBDB :: Fetch(char *key, uint32_t klen, string &val)
{
	try{		// Acquire a cursor for the table.
		Dbc *dbcp;
		db->cursor(NULL, &dbcp, 0);
		// Walk through the table, printing the key/data pairs.
		Dbt bkey(key, klen+1);
		Dbt data;
		if(dbcp->get(&bkey, &data, DB_SET) == 0) 
		{
			val = (char *)data.get_data();
		}
		dbcp->close();
	}
	catch (DbException &dbe) {
		cerr << "cobweb: " << dbe.what() << "\n";
                return false;
	}
        return true;
}
